Using FISSA with CNMF from MATLAB

CNMF is blind source separation toolbox for cell detection and signal extraction.

Here we illustrate how one can use the ROIs detected by CNMF, and use FISSA to extract and decontaminate the traces.

In this tutorial, we assume the user is using the MATLAB implementation of CNMF. As such, this also serves as a tutorial on how to import data from MATLAB into Python to use with FISSA.

However, note that there is also a Python implementation of CNMF, which you can use instead to keep your whole workflow in Python.

Reference: Pnevmatikakis, E.A., Soudry, D., Gao, Y., Machado, T., Merel, J., ... & Paninski, L. (2016). Simultaneous denoising, deconvolution, and demixing of calcium imaging data. Neuron 89(2):285-299, doi: 10.1016/j.neuron.2015.11.037.

Imports


In [1]:
# FISSA toolbox
import fissa

# Matfile loading utility
from scipy.io import loadmat

# Plotting toolbox, with notebook embedding options
import holoviews as hv
%load_ext holoviews.ipython
%output widgets='embed'


Running CNMF in MATLAB, and importing into Python

We ran CNMF in MATLAB using the run_pipeline.m script available from the CNMF repository on our example data (found at ../exampleData/20150529/).

We saved the Coor and F_df variables generated by that script into a .mat file (cNMFdata.mat) which we now load here.


In [2]:
# Load data from cNMFdata.mat file
cNMFdata = loadmat('cNMFdata')['dat']

# Get the F_df recording traces out of the loaded object
F_df = cNMFdata['F_df'][0, 0]

# Get the ROI outlines out of the loaded object
Coor = cNMFdata['Coor'][0, 0]

Show detected cells

We can render the ROIs as curves in holoviews.


In [3]:
# Plotting lines surrounding each of the ROIs
fig = hv.Overlay()
for i in range(len(Coor)):
    x = Coor[i, 0][0]
    y = Coor[i, 0][1]
    fig *= hv.Curve(zip(x, y))

fig


Out[3]:

Running FISSA on cells detected by CNMF

FISSA needs ROIs to be provided either as an ImageJ zip file, or a set of numpy arrays.

CNMF can output ROIs in coordinates (as we imported above), which can be directly read into FISSA. A given roi after importing from MATLAB is given as

Coor[i, 0]

FISSA expects a set of rois to be given as a list of lists,

[[roiA1, roiA2, roiA3, ...]]

so we will need to change the format of the ROIs first.


In [4]:
numROI = len(Coor)
rois_FISSA = [[Coor[i, 0][0], Coor[i, 0][1]] for i in range(numROI)]

Which can then be put into FISSA and run as follows.


In [5]:
output_folder = 'fissa_cnmf_example'
tiff_folder = 'exampleData/20150529/'

exp = fissa.Experiment(tiff_folder, [rois_FISSA], output_folder)
exp.separate(redo_prep=True)


Doing region growing and data extraction....
Doing signal separation....
NMF converged after 1085 iterations.
Finished ROI number 0
NMF converged after 1003 iterations.
Finished ROI number 1
NMF converged after 1139 iterations.
Finished ROI number 4
NMF converged after 1063 iterations.
Finished ROI number 2
NMF converged after 1223 iterations.
Finished ROI number 3

Plotting the results

Let's plot the traces for cells as they were detected by CNMF, and after removing neuropile with FISSA.


In [6]:
%%opts Curve {+axiswise}


def plot_cell_regions(roi_polys, plot_neuropil=False):
    '''
    Plot a single cell region, using holoviews.
    '''
    out = hv.Overlay()

    if plot_neuropil:
        # Plot the neuropil as well as the ROI
        n_region = len(roi_polys)
    else:
        # Just plot the ROI, not the neuropil
        n_region = 1

    for i_region in range(n_region):
        x = roi_polys[i_region][0][:, 1]
        y = roi_polys[i_region][0][:, 0]
        out *= hv.Curve(zip(x, y))

    return out


i_trial = 0

# Generate outlines around for all detected regions, indicating neuropil subregions
region_plots = {
    i_cell: plot_cell_regions(exp.roi_polys[i_cell, i_trial], plot_neuropil=True)
    for i_cell in range(exp.nCell)
}

# Generate plots for raw extracts and neuropil removed
traces_plots = {
    i_cell: hv.Curve(exp.raw[i_cell][i_trial][0, :], label='CNMF') *
            hv.Curve(exp.result[i_cell][i_trial][0, :], label='FISSA')
    for i_cell in range(exp.nCell)
}

# Get average image
avg_img = hv.Raster(exp.means[i_trial])

# Render holoviews
avg_img * hv.HoloMap(region_plots, kdims=['Cell']) * fig + hv.HoloMap(traces_plots, kdims=['Cell'])


Out[6]:

(A) ROI contours, and the neuropil subregions defined by FISSA for the current cell.

(B) Signal extracted by CNMF (blue), and after decontaminating with FISSA (red)